package com.markerhub.controller;

import com.markerhub.entity.Category;
import com.markerhub.repository.CategoryRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;



@ResponseBody
@Controller
@RequestMapping("/category")
public class CategoryController {

    @Autowired
    private CategoryRepository categoryRepository;
    @GetMapping("/unsorted")
    public Page<Category> unsorted(@RequestParam(name="page",defaultValue="0")Integer page, @RequestParam(name="size",defaultValue="15") Integer size){
        //page:查询的页
        //size：每页显示的数量
        Pageable pageable = PageRequest.of(page,size) ;
        return categoryRepository.findAll(pageable);
    }

    @GetMapping("hierarchy")
    public List<CategoryHierarchyNode> findAll(){
        List<Category> unsorted = categoryRepository.findAll();

        int total = unsorted.size();
        return recursivelyBuildCategoryHierarchy(unsorted.toArray(new Category[total]), total);
    }

    public static class CategoryHierarchyNode extends com.markerhub.entity.Category {
        @javax.persistence.Transient
        private List<CategoryHierarchyNode> subCategories;

        public CategoryHierarchyNode() {
            subCategories = new ArrayList<>();
        }

        public List<CategoryHierarchyNode> getSubCategories() {
            return subCategories;
        }

        public void setSubCategories(List<CategoryHierarchyNode> categories) {
            subCategories = categories;
        }

        public void addSubCategory(CategoryHierarchyNode category) {
            subCategories.add(category);
        }
    }

    private static final List<CategoryHierarchyNode> EmptyList = new ArrayList<>();

    /**
     * 递归整理所有Category分类
     *
     * @param unsorted 待整理的结点
     * @param total 待整理的结点个数
     * @return CategoryHierarchy分类层级关系结构
     */
    private List<CategoryHierarchyNode> recursivelyBuildCategoryHierarchy(Category[] unsorted, int total) {
        if (total <= 0) {
            return EmptyList; // 递归终止条件1
        }

        // 哈希映射表, 方便搜索分类号ID
        Map<Integer, Integer> map = new HashMap<>();///< key为分类号ID整数，value为数组下标i(例如unsorted[i])
        for (int i = 0; i < total; i++) {
            int categoryId = unsorted[i].getId();
            map.put(categoryId, i);
        }

        // 无父母结点则为孤儿结点
        List<Integer> orphanCategoryList = new ArrayList<>();///< 存储无上级分类的孤儿分类，只记录分类ID号足矣

        // 有父母节点则为次级子节点
        Category[] normalCategoryList = new Category[total];///< 存储分类的节点

        // 遍历所有结点
        int cnt = 0;
        for (int i = 0; i < total; i++) {
            int parentCategoryId = unsorted[i].getPid();
            if (map.containsKey(parentCategoryId)) { // 检查上级结点是否存在
                normalCategoryList[cnt++] = unsorted[i]; // 有上级结点则当前为普通次级结点
                continue;
            }
            orphanCategoryList.add(unsorted[i].getId()); // 无父母则为孤儿结点
        }
        if (orphanCategoryList.size() <= 0 && cnt > 0) {
            // 递归终止条件2, 剩余结点中可能存在循环依赖式脏数据, 可以忽略之
            return EmptyList;
        }

        // 对剩余结点进行递归处理, 找出下一级子结点
        List<CategoryHierarchyNode> children =
                recursivelyBuildCategoryHierarchy(normalCategoryList, cnt);

        // 创建新的List列表, 用于输出分层结果
        List<CategoryHierarchyNode> hierarchy = new ArrayList<>(); // 变长数组, 以数组形式存放分类层级关系树
        Map<Integer, Integer> where = new HashMap<>(); // key=CategoryID号, value=数组下标j(例如hierarchy[j])
        int j = 0;
        for (Integer categoryId : orphanCategoryList) {
            int i = map.get(categoryId);

            CategoryHierarchyNode node = new CategoryHierarchyNode();
            node.setId(unsorted[i].getId());
            node.setName(unsorted[i].getName());
            node.setPid(unsorted[i].getPid());

            hierarchy.add(node);
            where.put(categoryId, j++);
        }
        // 遍历所有子节点, 放入树状结果并返回给上一级递归函数
        for (CategoryHierarchyNode child : children) {
            int parentCategoryId = child.getPid();
            j = where.get(parentCategoryId);
            hierarchy.get(j).addSubCategory(child);
        }
        return hierarchy;
    }
}
